package com.intelligent.system.common.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.intelligent.system.common.dto.TagCreateAndAssociateDTO;
import com.intelligent.system.common.dto.TagDTO;
import com.intelligent.system.common.dto.TagPageDTO;
import com.intelligent.system.common.dto.TagQueryDTO;
import com.intelligent.system.common.entity.Tag;
import com.intelligent.system.common.entity.TagObjectMap;
import com.intelligent.system.common.exception.CustomException;
import com.intelligent.system.common.mapper.TagMapper;
import com.intelligent.system.common.mapper.TagObjectMapMapper;
import com.intelligent.system.common.response.ResultDO;
import com.intelligent.system.common.service.TagService;
import com.intelligent.system.common.utils.SnowflakeIdUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;
import java.util.Collections;
import java.util.Objects;

/**
 * 标签服务实现类
 */
@Slf4j
@Service
public class TagServiceImpl extends ServiceImpl<TagMapper, Tag> implements TagService {

    @Autowired
    private TagMapper tagMapper;

    @Autowired
    private TagObjectMapMapper tagObjectMapMapper;

    @Resource
    private SnowflakeIdUtils idUtils;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDO<List<TagDTO>> searchTags(TagQueryDTO queryDTO) {
        try {
            // 参数校验
            if (Objects.isNull(queryDTO)) {
                return ResultDO.error(400, "查询参数不能为空");
            }
            if (StringUtils.isBlank(queryDTO.getTagName())) {
                return ResultDO.error(400, "标签名称不能为空");
            }

            log.info("开始搜索标签，查询参数：{}", queryDTO);

            // 构建查询条件
            LambdaQueryWrapper<Tag> wrapper = new LambdaQueryWrapper<>();
            wrapper.like(Tag::getTagName, queryDTO.getTagName())
                    .orderByDesc(Tag::getCreateTime);  // 按创建时间倒序排序

            // 执行查询
            List<Tag> tags = this.list(wrapper);
            if (tags.isEmpty()) {
                log.info("搜索标签未找到匹配结果");
                return ResultDO.success(Collections.emptyList());
            }

            // 转换为DTO
            List<TagDTO> tagDTOs = tags.stream().map(tag -> {
                TagDTO tagDTO = new TagDTO();
                BeanUtils.copyProperties(tag, tagDTO);
                return tagDTO;
            }).collect(Collectors.toList());

            log.info("搜索标签成功，找到{}条记录", tagDTOs.size());

            return ResultDO.success(tagDTOs);
        } catch (Exception e) {
            log.error("搜索标签发生异常", e);
            return ResultDO.error(500, "搜索标签失败：" + e.getMessage());
        }
    }

    @Override
    public ResultDO<TagDTO> getById(Long id) {
        try {
            Tag tag = tagMapper.selectById(id);
            if (tag == null) {
                return ResultDO.error(404, "标签不存在");
            }
            TagDTO dto = new TagDTO();
            BeanUtils.copyProperties(tag, dto);
            return ResultDO.success(dto);
        } catch (Exception e) {
            log.error("根据ID查询标签失败", e);
            throw new CustomException("根据ID查询标签失败：" + e.getMessage(), 500);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDO<Void> saveTag(TagDTO tagDTO) {
        try {
            // 检查标签名称是否已存在
            if (tagMapper.selectCount(new LambdaQueryWrapper<Tag>()
                    .eq(Tag::getTagName, tagDTO.getTagName())) > 0) {
                return ResultDO.error(400, "标签名称已存在");
            }
            
            Tag tag = new Tag();
            BeanUtils.copyProperties(tagDTO, tag);
            tag.setId(idUtils.nextId());
            if (tagMapper.insert(tag) <= 0) {
                return ResultDO.error(500, "新增标签失败");
            }
            return ResultDO.success(null);
        } catch (Exception e) {
            log.error("新增标签失败", e);
            throw new CustomException("新增标签失败：" + e.getMessage(), 500);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDO<Void> updateTag(TagDTO tagDTO) {
        try {
            // 检查标签是否存在
            Tag existingTag = tagMapper.selectById(tagDTO.getId());
            if (existingTag == null) {
                return ResultDO.error(404, "标签不存在");
            }
            
            // 检查标签名称是否重复
            if (!existingTag.getTagName().equals(tagDTO.getTagName()) &&
                tagMapper.selectCount(new LambdaQueryWrapper<Tag>()
                    .eq(Tag::getTagName, tagDTO.getTagName())) > 0) {
                return ResultDO.error(400, "标签名称已存在");
            }
            
            Tag tag = new Tag();
            BeanUtils.copyProperties(tagDTO, tag);
            
            if (tagMapper.updateById(tag) <= 0) {
                return ResultDO.error(500, "更新标签失败");
            }
            return ResultDO.success(null);
        } catch (Exception e) {
            log.error("更新标签失败", e);
            throw new CustomException("更新标签失败：" + e.getMessage(), 500);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDO<Void> removeById(Long id) {
        try {
            // 检查标签是否存在
            Tag tag = tagMapper.selectById(id);
            if (tag == null) {
                return ResultDO.error(404, "标签不存在");
            }
            
            // 检查标签是否被使用
            Long count = tagObjectMapMapper.selectCount(new LambdaQueryWrapper<TagObjectMap>()
                    .eq(TagObjectMap::getTagId, id));
            if (count > 0) {
                return ResultDO.error(400, "标签已被使用，无法删除");
            }
            
            if (tagMapper.deleteById(id) <= 0) {
                return ResultDO.error(500, "删除标签失败");
            }
            return ResultDO.success(null);
        } catch (Exception e) {
            log.error("删除标签失败", e);
            throw new CustomException("删除标签失败：" + e.getMessage(), 500);
        }
    }

    @Override
    public ResultDO<IPage<TagDTO>> page(TagPageDTO pageDTO) {
        try {
            // 创建分页对象
            Page<Tag> page = new Page<>(pageDTO.getCurrent(), pageDTO.getSize());
            
            LambdaQueryWrapper<Tag> queryWrapper = new LambdaQueryWrapper<Tag>()
                    .like(StringUtils.isNotBlank(pageDTO.getTagName()), Tag::getTagName, pageDTO.getTagName());

            // 处理排序
            if (StringUtils.isNotBlank(pageDTO.getOrderField())) {
                if ("desc".equalsIgnoreCase(pageDTO.getOrderType())) {
                    queryWrapper.orderByDesc(Tag::getCreateTime);
                } else {
                    queryWrapper.orderByAsc(Tag::getCreateTime);
                }
            } else {
                queryWrapper.orderByDesc(Tag::getCreateTime);
            }
            
            IPage<Tag> tagPage = tagMapper.selectPage(page, queryWrapper);
            return ResultDO.success(tagPage.convert(tag -> {
                TagDTO dto = new TagDTO();
                BeanUtils.copyProperties(tag, dto);
                return dto;
            }));
        } catch (Exception e) {
            log.error("分页查询标签列表失败", e);
            throw new CustomException("分页查询标签列表失败：" + e.getMessage(), 500);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDO<?> createAndAssociate(TagCreateAndAssociateDTO dto) {
        try {
            // 1. 根据标签名称查询标签是否存在
            Tag existingTag = tagMapper.selectOne(new LambdaQueryWrapper<Tag>()
                    .eq(Tag::getTagName, dto.getTagName()));
            
            Tag tag;
            if (existingTag == null) {
                // 2. 如果标签不存在，创建新标签
                tag = new Tag();
                tag.setId(idUtils.nextId());
                tag.setTagName(dto.getTagName());
                if (tagMapper.insert(tag) <= 0) {
                    return ResultDO.error(500, "创建标签失败");
                }
            } else {
                tag = existingTag;
            }
            
            // 3. 检查是否已经存在关联关系
            Long count = tagObjectMapMapper.selectCount(new LambdaQueryWrapper<TagObjectMap>()
                    .eq(TagObjectMap::getTagId, tag.getId())
                    .eq(TagObjectMap::getObjectId, dto.getObjectId())
                    .eq(TagObjectMap::getObjectType, dto.getObjectType()));
            
            if (count > 0) {
                // 4. 如果已存在关联关系，直接返回标签信息
                TagDTO tagDTO = new TagDTO();
                BeanUtils.copyProperties(tag, tagDTO);
                return ResultDO.success(tagDTO);
            }
            
            // 5. 创建关联关系
            TagObjectMap tagObjectMap = new TagObjectMap();
            tagObjectMap.setTagId(tag.getId());
            tagObjectMap.setObjectId(dto.getObjectId());
            tagObjectMap.setObjectType(dto.getObjectType());
            
            if (tagObjectMapMapper.insert(tagObjectMap) <= 0) {
                throw new CustomException("创建标签关联关系失败", 500);
            }

            return ResultDO.success(null);
            
        } catch (Exception e) {
            log.error("创建标签并关联对象失败", e);
            throw new CustomException("创建标签并关联对象失败：" + e.getMessage(), 500);
        }
    }

    @Override
    public ResultDO<List<TagDTO>> listByObjectId(Long objectId, Integer objectType) {
        try {
            // 1. 查询对象关联的标签映射
            List<TagObjectMap> tagObjectMaps = tagObjectMapMapper.selectList(
                new LambdaQueryWrapper<TagObjectMap>()
                    .eq(TagObjectMap::getObjectId, objectId)
                    .eq(TagObjectMap::getObjectType, objectType)
            );

            if (CollectionUtils.isEmpty(tagObjectMaps)) {
                return ResultDO.success(Collections.emptyList());
            }

            // 2. 获取标签ID列表
            List<Long> tagIds = tagObjectMaps.stream()
                .map(TagObjectMap::getTagId)
                .collect(Collectors.toList());

            // 3. 查询标签详情
            List<Tag> tags = tagMapper.selectList(
                new LambdaQueryWrapper<Tag>()
                    .in(Tag::getId, tagIds)
                    .orderByDesc(Tag::getCreateTime)
            );
            
            // 4. 转换为DTO
            List<TagDTO> dtos = tags.stream().map(tag -> {
                TagDTO dto = new TagDTO();
                BeanUtils.copyProperties(tag, dto);
                return dto;
            }).collect(Collectors.toList());
            
            return ResultDO.success(dtos);
        } catch (Exception e) {
            log.error("根据对象ID和对象类型查询标签列表失败", e);
            throw new CustomException("根据对象ID和对象类型查询标签列表失败：" + e.getMessage(), 500);
        }
    }
} 